home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 6 / ddj_cspc.zip / STARR.LST < prev    next >
File List  |  1989-11-21  |  21KB  |  885 lines

  1. _C LIST MANAGER_
  2. by Robert Starr
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. /*    makelist- list management package
  8.     RF Starr
  9.     2639 Valley Field Dr.
  10.     SugarLand, TX 77479
  11. */
  12.  
  13. #include <stdio.h>
  14. #include <varargs.h>
  15. #ifdef MSDOS
  16. #include <stdlib.h>
  17. #include <malloc.h>
  18. #else
  19. #define void char
  20. extern char *malloc();
  21. #endif
  22.  
  23. /*#define DEBUG*/
  24.  
  25. #ifdef DEBUG
  26. #define Debug(x) x
  27. #else
  28. #define Debug(x)
  29. #endif
  30.  
  31. typedef struct data DATA;
  32. typedef struct list LIST;
  33. typedef struct prop PROP;
  34.  
  35. struct data {
  36.     void *data;    /* space for list->nentries instances of data */
  37.     DATA *next;    /* next list->nentries collection of data */
  38. };
  39.  
  40. struct prop {
  41.     void *dataptr;    /* to what data item this property associates */
  42.     void *propval;    /* property value to associate with the data */
  43.     void *propsym;    /* optional symbol (usually char *) to associate */
  44.     PROP *next;
  45. };
  46.  
  47. struct list {
  48.     int  entrysize;        /* size of each data entry in bytes */
  49.     int  nentries;        /* # entries to grab per malloc call */
  50.     int  empty_slots;    /* empty slots left in current data block */
  51.     int  nitems;        /* total items saved in this list */
  52.     int  ecount;        /* where we are when reading back list */
  53.     int  fblock;
  54.     DATA *fdata;
  55.     PROP *prop;       /* optional property list for this list */
  56.     DATA *data;       /* linked list for the actual data of this list */
  57.     DATA *hidata;       /* highest allocated data block (for efficiency) */
  58. };
  59.  
  60. /* Internal malloc routine */
  61. /*#define MEMCHK*/
  62. #ifdef MEMCHK
  63. static FILE *memfp = NULL;
  64. #endif
  65. static void *
  66. imalloc(size)
  67. int size; {
  68.     void *ptr = malloc(size);
  69. #ifdef MEMCHK
  70.     if (!memfp) memfp = fopen("meminfo","w");
  71. #endif
  72.     if (!ptr) {
  73.         fprintf(stderr,"malloc error: no free memory left.\n");
  74.         fflush(stderr);
  75.     }
  76. #ifdef MEMCHK
  77.     fprintf(memfp,"%x malloc\n",ptr);
  78.     fflush(memfp);
  79. #endif
  80.     return ptr;
  81. }
  82.  
  83. static void *
  84. ifree(addr)
  85. void *addr; {
  86.     free(addr);
  87. #ifdef MEMCHK
  88.     fprintf(memfp,"%x free\n",addr);
  89.     fflush(memfp);
  90. #endif
  91. }
  92.  
  93. /* Build, initialize, and return an empty list */
  94. void *
  95. makelist(esize,nentries)
  96. int esize,nentries; {
  97.     LIST *list = imalloc(sizeof(LIST)+sizeof(DATA)+esize*nentries);
  98.     void *dp   = imalloc(sizeof(DATA)+esize*nentries);
  99.     if (!list || !dp) return NULL;
  100.     list->data = (DATA *)dp;
  101.     list->data->data = (char *)dp + sizeof(DATA);
  102.     list->entrysize = esize;
  103.     list->nentries = nentries;
  104.     list->empty_slots = nentries;
  105.     list->nitems = 0;
  106.     list->ecount = 0;
  107.     list->fblock = 0;
  108.     list->fdata = NULL;
  109.     list->prop = (PROP *)NULL;
  110.     list->hidata = list->data;
  111.     list->data->next = NULL;
  112.     return (void *)list;
  113. }
  114.  
  115. /*     Put items on property list for this data item.  Propsym is the
  116.     property symbol, and val is a pointer to a _static_ are where the
  117.     data for this property resides.
  118. */
  119. putproplist(list,dataptr,propsym,val)
  120. LIST *list;
  121. void *dataptr,*val;
  122. char *propsym; {
  123.     PROP *newprop = (PROP *)imalloc(sizeof(PROP));
  124.     PROP *topprop = list->prop;    
  125.     if (!list) return NULL;
  126.     if (!newprop) return;
  127.     newprop->dataptr = dataptr;
  128.     newprop->propsym = propsym;
  129.     newprop->propval = val;
  130.     newprop->next = topprop;
  131.     list->prop = newprop;
  132. }
  133.  
  134. /*    Read an item off of the property list for a particular data
  135.     item.  NULL returned if there is none.
  136. */
  137. void *
  138. getproplist(list,dataptr,propsym)
  139. LIST *list;
  140. void *dataptr,*propsym; {
  141.     PROP *p;
  142.     void *propval = NULL;
  143.     if (!list) return NULL;
  144.     p = list->prop;
  145.     while (p) {
  146.         int  fsym = !strcmp(p->propsym,propsym);
  147.         if ((!dataptr && fsym) || (p->dataptr == dataptr && fsym)) {
  148.             propval = p->propval;
  149.             break;
  150.         }
  151.         p = p->next;
  152.     }
  153.     return propval;
  154. }
  155.  
  156. /* Find data item associated with a property name */
  157. void *
  158. findprop(list,propsym)
  159. LIST *list;
  160. char *propsym; {
  161.     PROP *p;
  162.     if (!list) return NULL;
  163.     p = list->prop;
  164.     while (p) {
  165.         if (!strcmp(p->propsym,propsym)) return p->dataptr;
  166.         p = p->next;
  167.     }
  168.     return NULL;
  169. }
  170.  
  171. /* Append data to the specified list */
  172. static void
  173. whereis(list,ndx,walk,put)
  174. LIST *list;
  175. int  *walk,*put; {
  176.     *walk = ndx / list->nentries;
  177.     *put  = ndx % list->nentries;
  178. }
  179.  
  180. /* Remove last entry on the specified list... adjust struct accordingly */
  181. void *
  182. poplist(list)
  183. LIST *list; {
  184.     DATA *org;
  185.     void *dp = NULL;
  186.     unsigned char *data;
  187.     int  put;
  188.     if (!list) return NULL;
  189.     if (!list->nitems) return dp;
  190.     org = list->data;
  191.     list->empty_slots++;
  192.     list->nitems--;
  193.     if (list->empty_slots == list->nentries) {
  194.         while (org->next) org = org->next;
  195.         put  = list->nitems % list->nentries;
  196.         data = (unsigned char *)org->data;
  197.         dp = (void *)(data+(list->entrysize*put));
  198.         if (org->next) ifree(org->next), org->next = NULL;
  199.         list->hidata = org;
  200.     }
  201.     return dp;
  202. }
  203.  
  204. /* calculate data pointer for the ndx entry */
  205. static void *
  206. calcdp(list,ndx)
  207. LIST *list;
  208. int  ndx; {
  209.     DATA *pdata;
  210.     unsigned char *dp;
  211.     int  size = (list) ? list->entrysize :0;
  212.     int  max  = (list) ? list->nitems : 0;
  213.     int  walk,put;
  214.     if (!list || ndx >= max) return (void *)NULL;
  215.     whereis(list,ndx,&walk,&put);
  216.     pdata = list->data;
  217.     while (walk--) pdata = pdata->next;
  218.     dp = (unsigned char *)pdata->data;
  219.     return (char *)(dp+(size*put));
  220. }
  221.  
  222. /* Return pointer to data which is last on the list */
  223. void *
  224. toplist(list)
  225. LIST *list; {
  226.     void *dp = NULL;
  227.     void *fetchlist();
  228.     unsigned char *data;
  229.     int put;
  230.     if (!list || !list->nitems) return NULL;
  231.     return calcdp(list,list->nitems-1);
  232. }
  233.  
  234. /* append a data item onto specified list */
  235. void *
  236. appendlist(list,data)
  237. LIST *list;
  238. void *data; {
  239.     DATA *pdata;
  240.     void *where;
  241.     unsigned char *dp;
  242.     int  walk,put,size;
  243.     if (!list) return NULL;
  244.     size = list->entrysize;
  245.     whereis(list,list->nitems,&walk,&put);
  246.     pdata = list->hidata;
  247.     if (!list->empty_slots) {
  248.         void *mem = imalloc(sizeof(DATA)+size*list->nentries);
  249.         if (!mem) return NULL;
  250.         list->hidata = pdata = pdata->next = (DATA *)mem;
  251.         pdata->data = (void *)((char *)mem+sizeof(DATA));
  252.         pdata->next = NULL;
  253.         list->empty_slots = list->nentries;
  254.     }
  255.     dp = (unsigned char *)pdata->data;
  256.     where = (char *)(dp+(put*size));
  257.     memcpy(where,data,size);
  258.     list->empty_slots--;
  259.     list->nitems++;
  260.     return where;
  261. }
  262.  
  263. /* return index of NEXT list entry */
  264. listindex(list)
  265. LIST *list; {
  266.     return list->nitems;
  267. }
  268.  
  269. /* append a data item onto specified list with property value information */
  270. void *
  271. pappendlist(list,data,propsym,val)
  272. LIST *list;
  273. void *data,*val;
  274. char *propsym; {
  275.     void *dataptr = appendlist(list,data);
  276.     if (dataptr) putproplist(list,dataptr,propsym,val);
  277.     return dataptr;
  278. }
  279.  
  280. /* Just like appendlist... new name for compatibility with poplist */
  281. void *
  282. pushlist(list,data)
  283. LIST *list;
  284. void *data; {
  285.     if (!list) return NULL;
  286.     return appendlist(list,data);
  287. }
  288.  
  289. /* Fetch a specific data item off of list... ndx is 0-based */
  290. void *
  291. fetchlist(list,ndx)
  292. LIST *list;
  293. int ndx; {
  294.     DATA *pdata;
  295.     unsigned char *dp;
  296.     int  size = list->entrysize;
  297.     int  max  = list->nitems;
  298.     int  walk,put;
  299.     if (!list) return NULL;
  300.     if (ndx >= max) return (void *)NULL;
  301.     whereis(list,ndx,&walk,&put);
  302.     if (walk == list->fblock)
  303.         list->fdata = pdata = (list->fdata) ? list->fdata : list->data;
  304.     else {
  305.         pdata = list->data;
  306.         list->fblock = walk;
  307.         while (walk--)
  308.             pdata = pdata->next;
  309.         list->fdata = pdata;
  310.     }
  311.     dp = (unsigned char *)pdata->data;
  312.     Debug(printf("fetchlist: getting data from %x\n",dp+(size*put)));
  313.     return (char *)(dp+(size*put));
  314. }
  315.  
  316. /* reset pointer used by walklist */
  317. rewindlist(list)
  318. LIST *list; {
  319.     if (list) list->ecount = 0;
  320. }
  321.  
  322. /* walk down the list, returning each data item 'till there ain't no more */
  323. void *
  324. walklist(list)
  325. LIST *list; {
  326.     DATA *pdata;
  327.     unsigned char *dp;
  328.     int  size = list->entrysize;
  329.     int  max  = list->nitems;
  330.     int  index = list->ecount;
  331.     int  walk,put;
  332.     if (!list) return NULL;
  333.     dp = (unsigned char *)fetchlist(list,index);
  334.     if (!dp) 
  335.         list->ecount = 0;
  336.     else 
  337.         list->ecount++;
  338.     return (list->ecount) ? (void *)dp : (void *)NULL;
  339. }
  340.  
  341. /* malloc size bytes, and add address of malloced space to the list */
  342. void *
  343. malloclist(list,size)
  344. LIST *list;
  345. int  size; {
  346.     void *dp;
  347.     if (!list) return NULL;
  348.     dp = imalloc(size);
  349.     if (dp) appendlist(list,&dp);
  350.     return dp;
  351. }
  352.  
  353. /* Free up all malloced data associated with the specified list */
  354. freelist(list)
  355. LIST *list; {
  356.     fl(list,0);
  357. }
  358.  
  359. /* garbage collect list... assume all data in list is malloced ptrs */
  360. gclist(list)
  361. LIST *list; {
  362.     fl(list,1);
  363. }
  364.  
  365. /* Free the list up.  If freedp != 0, free each data pointer as well */
  366. static
  367. fl(list,freedp)
  368. LIST *list; {
  369.     DATA *pdata,*ppd;
  370.     PROP *p = list->prop;
  371.     if (!list) return;
  372.     pdata = list->data;
  373.     if (freedp) {
  374.         void *dp;
  375.         rewindlist(list);
  376.         while (dp=walklist(list))
  377.             ifree(*(char **)dp);
  378.     }
  379.     /* free all malloced data */
  380.     while (pdata) {
  381.         DATA *next = pdata->next;
  382.         ifree(pdata);
  383.         pdata = next;
  384.     }
  385.     /* free all malloced property info */
  386.     while (p) {
  387.         PROP *n = p->next;
  388.         ifree(p);
  389.         p = n;
  390.     }
  391.     ifree(list);
  392. }
  393.  
  394. /*     given a list of functions, invoke the function with the specified
  395.     property tag with the arguments supplied.
  396. */
  397.  
  398. /*funclist(list,prop,args) (actual calling argument list)*/
  399. int
  400. funclist(va_alist)
  401. va_dcl {
  402.     void *list;
  403.     void *prop;
  404.     void *vp;    
  405.     int  (*func)();
  406.     va_list argmark;
  407.     va_start(argmark);
  408.     list = va_arg(argmark,void *);
  409.     prop = va_arg(argmark,void *);
  410.     vp = findprop(list,prop);
  411.     if (!vp) return 0;
  412.     func = *(int (**)())vp;
  413.     return (*func)(argmark);
  414. }
  415.  
  416.  
  417. [LISTING TWO]
  418.  
  419. /* Header file for makelist */
  420.  
  421. /* Remove this if you don't have ANSI C compiler */
  422. #define ANSIC
  423.  
  424. #ifndef ANSIC
  425. #define void char
  426. #endif
  427.  
  428. /* Usage: e.g. deref(int,x) or deref(char *,x) */
  429. #define deref(type,x)  *((type*)(x))
  430.  
  431. /* Function prototypes/declarations */
  432. /*----------------------------------------------------------------------*/
  433. #ifdef ANSIC
  434. extern  void *makelist(int esize,int nentries);
  435. extern  int putproplist(void *list,void *dataptr,char *propsym,void *val);
  436. extern  void *getproplist(void *list,void *dataptr,void *propsym);
  437. extern  void *toplist(void *list);
  438. extern  void *poplist(void *list);
  439. extern  void *appendlist(void *list,void *data);
  440. extern  void *pappendlist(void *list,void *data,char *propsym,char *val);
  441. extern  void *pushlist(void *list,void *data);
  442. extern  void *fetchlist(void *list,int ndx);
  443. extern  void *walklist(void *list);
  444. extern  void rewindlist(void *list);
  445. extern  void *malloclist(void *list,int size);
  446. extern  int freelist(void *list);
  447. extern  int gclist(void *list);
  448. extern  int funclist(void *,...);
  449. extern  int listindex(void *list);
  450. #else
  451. extern  void *makelist();
  452. extern  int putproplist();
  453. extern  void *getproplist();
  454. extern  void *toplist();
  455. extern  void *poplist();
  456. extern  void *appendlist();
  457. extern  void *pappendlist();
  458. extern  void *pushlist();
  459. extern  void *fetchlist();
  460. extern  void *walklist();
  461. extern  void rewindlist();
  462. extern  void *malloclist();
  463. extern  int freelist();
  464. extern  int gclist();
  465. extern  int funclist();
  466. extern  int listindex();
  467. #endif
  468. /*----------------------------------------------------------------------*/
  469.  
  470.  
  471. Example 1: A list of integers
  472.  
  473.  
  474. #ifdef Explanation
  475. ----------------------------------------------------------------------
  476. Make a list to hold integers, and put 100 integers onto the list.
  477. Then, play back the list.
  478. ----------------------------------------------------------------------
  479. #endif
  480.  
  481. #include <stdio.h>
  482. #include "makelist.h"
  483.  
  484. main() {
  485.     void *list,*dp;
  486.     int  ii;
  487.     /* make a list to hold integers */
  488.     list = makelist(sizeof(int),10);
  489.     /* put 100 integers on list */
  490.     for (ii=0 ; ii < 100 ; ii++)
  491.         appendlist(list,&ii);
  492.     /* use fetchlist to read back list */
  493.     for (ii=0 ; ii < 100 ; ii++) {
  494.         void *dp = fetchlist(list,ii);
  495.         printf("Entry %2d = %d\n",ii,*(int *)dp);
  496.     }
  497.     freelist(list);
  498. }
  499.  
  500.  
  501. Example 2: A list of strings
  502.  
  503.  
  504. #ifdef Explanation
  505. ----------------------------------------------------------------------
  506. Demonstrates the putting of strings on a list and use of gclist.  
  507. ----------------------------------------------------------------------
  508. #endif
  509.  
  510. #include <stdio.h>
  511. #include "makelist.h"
  512.  
  513. extern char *strdup();
  514.  
  515. main() {
  516.     char buffer[132];
  517.     void *list,*dp,*ptr;
  518.     int  ii;
  519.     int  cnt;
  520.     /* make list to hold strings */
  521.     list = makelist(sizeof(char *),10);
  522.     /* build the list of strings */
  523.     for (ii=0 ; ii < 30 ; ii++) {
  524.         sprintf(buffer,"text string %d",ii);
  525.         dp = strdup(buffer);
  526.         appendlist(list,&dp);
  527.     }
  528.     /* use walklist to view each string saved in list */
  529.     while (dp = walklist(list))
  530.         printf("%s\n",*((char **)dp));
  531.     /* free up list, as well as all malloced data */
  532.     gclist(list);
  533. }
  534.  
  535.  
  536.  Example 3: A list of structures
  537.  
  538.  
  539. #ifdef Explanation
  540. ----------------------------------------------------------------------
  541. Saving and retrieving structures on lists.  
  542. ----------------------------------------------------------------------
  543. #endif
  544.  
  545. #include <stdio.h>
  546. #include "makelist.h"
  547.  
  548. extern char *strdup();
  549. /* here is our data structure */
  550. struct foo {
  551.     char *name;
  552.     int  ndx;
  553. } foo;
  554.  
  555. main() {
  556.     void *list;
  557.     void *vp;
  558.     struct foo *fp;
  559.     int  ii,jj,kk;
  560.     char buffer[256];
  561.     /* make list to hold struct foo */
  562.      list = makelist(sizeof(struct foo),10);
  563.     /* build list of 30 instances of struct foo */
  564.     for (ii=0 ; ii < 30 ; ii++) {
  565.         sprintf(buffer,"foo element %d",ii);
  566.         foo.name = strdup(buffer);
  567.         foo.ndx = ii;
  568.         appendlist(list,&foo);
  569.     }
  570.     /* play back list.  note that vp is merely cast */
  571.     while (vp=walklist(list)) {
  572.         fp = (struct foo *)vp;
  573.         printf("%2d) %s\n",fp->ndx,fp->name);
  574.     }
  575.     /* free up each string malloced during list creation */
  576.     while (vp=walklist(list)) {
  577.         fp = (struct foo *)vp;
  578.         free(fp->name);
  579.     }
  580.     /* free the list itself */
  581.     freelist(list);
  582. }
  583.  
  584.  
  585. Example 4: Using malloclist()
  586.  
  587. #ifdef Explanation
  588. ----------------------------------------------------------------------
  589. We use malloclist to get memory space, rather than malloc.  This will
  590. automatically append malloced data onto a list (which you must provide),
  591. so that a single call to gclist will free not only the list, but all
  592. malloced space as well.  
  593. ----------------------------------------------------------------------
  594. #endif
  595.  
  596. #include <stdio.h>
  597. #include "makelist.h"
  598.  
  599. main() {
  600.     void *list,*dp,*ptr;
  601.  
  602.     printf("Exercising malloclist...\n");
  603.     list = makelist(sizeof(void *),10);
  604.  
  605.     ptr = "string #1";
  606.     dp = malloclist(list,strlen(ptr)+1);
  607.     strcpy(dp,ptr);
  608.     ptr = "string #2";
  609.     dp = malloclist(list,strlen(ptr)+1);
  610.     strcpy(dp,ptr);
  611.     ptr = "string #3";
  612.     dp = malloclist(list,strlen(ptr)+1);
  613.     strcpy(dp,ptr);
  614.     /* play back list */
  615.     while (dp = walklist(list))
  616.         printf("%s\n",*(char **)dp);
  617.     /* free up the list */
  618.     gclist(list);
  619. }
  620.  
  621.  
  622. Example 5: Pushing and poping a list
  623.  
  624. #ifdef Explanation
  625. ----------------------------------------------------------------------
  626. Demonstrate how to push & pop data off of a list.
  627. ----------------------------------------------------------------------
  628. #endif
  629.  
  630. #include <stdio.h>
  631. #include "makelist.h"
  632.  
  633. main() {
  634.     void *list,*dp,*ptr;
  635.     int  ii,jj,kk;
  636.     int  cnt;
  637.  
  638.     /* build list to hold integers */
  639.     list = makelist(sizeof(int),5);
  640.     /* push 10 integers onto list */
  641.     for (ii=0 ; ii < 10 ; ii++)
  642.         pushlist(list,&ii);
  643.     /* walk down list 10 times, popping an entry each time */
  644.     for (ii=0 ; ii < 10 ; ii++) {
  645.         extern void *toplist();
  646.         while (dp = walklist(list))
  647.             printf("%d\n",*(int *)dp);
  648.         dp = toplist(list);
  649.         printf("popping off %d\n",*(int *)dp);
  650.         poplist(list);
  651.     }
  652.     /* list is now empty */
  653.     printf("pushing onto list again\n");
  654.     for (ii=0 ; ii < 10 ; ii++)
  655.         pushlist(list,&ii);
  656.     /* veryify entire list */
  657.     while (dp = walklist(list))
  658.         printf("%d\n",*(int *)dp);
  659.     /* pop off an item at a time off list */
  660.     for (ii=0 ; ii < 10 ; ii++) {
  661.         extern void *toplist();
  662.         dp = toplist(list);
  663.         printf("popping off %d\n",*(int *)dp);
  664.         poplist(list);
  665.     }
  666.     /* ensure list is indeed empty */
  667.     printf("walking list again... should be empty\n");
  668.     while (dp = walklist(list))
  669.         printf("%d\n",*(int *)dp);
  670.     freelist(list);
  671. }
  672.  
  673.  
  674. Example 6: Property list usage
  675.  
  676.  
  677. #ifdef Explanation
  678. ----------------------------------------------------------------------
  679. Put 100 integers on a list.  Every 5th element on the list, add a
  680. special property value.
  681. ----------------------------------------------------------------------
  682. #endif
  683.  
  684. #include <stdio.h>
  685. #include "makelist.h"
  686.  
  687. extern char *strdup();
  688.  
  689. main() {
  690.     void *list,*dp,*ptr;
  691.     int  jj;
  692.     int  cnt;
  693.     void *nl = makelist(sizeof(int),20);
  694.  
  695.     for (jj=0 ; jj < 100 ; jj++) {
  696.         void *dp = appendlist(nl,&jj);
  697.         /* every 5th element, put something on property list */
  698.         if (!(jj%5)) {
  699.             char buffer[80];
  700.             sprintf(buffer,"list[%d]",jj);
  701.             putproplist(nl,dp,"MSG",strdup(buffer));
  702.         }
  703.     }
  704.     for (jj=0 ; jj < 100 ; jj++) {
  705.         void *dp = fetchlist(nl,jj);
  706.         char *ptr;
  707.         printf("%d\n",*(int *)dp);
  708.         if (!(jj%5)) {
  709.             void *p = (jj) ? dp : (void *)NULL;
  710.             printf("PROP: %s\n",ptr = getproplist(nl,p,"MSG"));
  711.             free(ptr);
  712.         }
  713.     }
  714.     freelist(nl);
  715. }
  716.  
  717.  
  718. Example 7: Property list usage w/pappendlist
  719.  
  720.  
  721. #ifdef Explanation
  722. ----------------------------------------------------------------------
  723. Make a list to hold integers, and put 100 integers onto the list.
  724. Then, play back the list.  For each integer put on the list, add
  725. a property value which uniquely identifies the data value.
  726. ----------------------------------------------------------------------
  727. #endif
  728.  
  729. #include <stdio.h>
  730. #include "makelist.h"
  731.  
  732. extern char *strdup();
  733.  
  734. main() {
  735.     void *list,*dp;
  736.     char *ptr,buffer[80];
  737.     int  ii;
  738.  
  739.     list = makelist(sizeof(int),10);
  740.  
  741.     /* put 100 integers on list, w/ prop to tell their index in ASCII */
  742.     for (ii=0 ; ii < 100 ; ii++) {
  743.         sprintf(buffer,"index %d",ii);
  744.         pappendlist(list,&ii,"OP",strdup(buffer));
  745.     }
  746.     /* get each integer off list, and show its property */
  747.     for (ii=0 ; ii < 100 ; ii++) {
  748.         void *dp = fetchlist(list,ii);
  749.         ptr = getproplist(list,dp,"OP");
  750.         printf("Entry %2d = %d, prop = %s\n",ii,*(int *)dp,ptr);
  751.         free(ptr);
  752.     }
  753.     freelist(list);
  754. }
  755.  
  756.  
  757. Example 8: A list of lists
  758.  
  759.  
  760. #ifdef Explanation
  761. ----------------------------------------------------------------------
  762. Build and populate a list of lists
  763. ----------------------------------------------------------------------
  764. #endif
  765.  
  766. #include <stdio.h>
  767. #include "makelist.h"
  768.  
  769. main() {
  770.     void *listlist;
  771.     int  ii,jj,kk;
  772.  
  773.     /* create a list of lists */
  774.      listlist = makelist(sizeof(void *),10);
  775.     /* build 10 lists to hold integers */
  776.     for (ii=0 ; ii < 10 ; ii++) {
  777.         void *vp = makelist(sizeof(int),10);
  778.         appendlist(listlist,&vp);
  779.     }
  780.     /* populate each of the 10 lists */
  781.     for (ii=0 ; ii < 10 ; ii++) {
  782.         void *list = *(void **)fetchlist(listlist,ii);
  783.         for (jj=0 ; jj < 20 ; jj++) {
  784.             kk = ii*100 + jj;
  785.             appendlist(list,&kk);
  786.         }
  787.     }
  788.     /* replay each of the 10 lists */
  789.     for (ii=0 ; ii < 10 ; ii++) {
  790.         void *list = *(void **)fetchlist(listlist,ii);
  791.         for (jj=0 ; jj < 20 ; jj++)
  792.             printf("List %d, data = %d\n",ii,*(int *)fetchlist(list,jj));
  793.     }
  794.     /* free all lists */
  795.     for (ii=0 ; ii < 10 ; ii++) {
  796.         void *list = *(void **)fetchlist(listlist,ii);
  797.         freelist(list);
  798.     }
  799.     freelist(listlist);
  800. }
  801.  
  802.  
  803. Example 9: A list of functions
  804.  
  805.  
  806. #ifdef Explanation
  807. ----------------------------------------------------------------------
  808. Demonstrate how to use build a list of functions and call them
  809. directly off of the list, with arguments.  
  810. ----------------------------------------------------------------------
  811. #endif
  812.  
  813. #include <stdio.h>
  814. #include <varargs.h>
  815. #include "makelist.h"
  816.  
  817. /* This function expects integer arguments, zero terminated */
  818. static
  819. foo(argmark)
  820. va_list argmark; {
  821.     int  i;
  822.     while (1) {
  823.         i = va_arg(argmark,int);
  824.         if (!i) break;
  825.         printf("%d\n",i);
  826.     }
  827. }
  828.  
  829. /* This function expects string arguments, NULL terminated */
  830. static
  831. goo(argmark)
  832. va_list argmark; {
  833.     char *ptr;
  834.     while (1) {
  835.         ptr = va_arg(argmark,char *);
  836.         if (!ptr) break;
  837.         printf("%s\n",ptr);
  838.     }
  839. }
  840.  
  841. /* This function expects a string, followed by an integer */
  842. static
  843. poo(argmark)
  844. va_list argmark; {
  845.     char *ptr;
  846.     int  i;
  847.     ptr = va_arg(argmark,char *);
  848.     i = va_arg(argmark,int);
  849.     printf("string = %s, int = %d\n",ptr,i);
  850. }
  851.  
  852. /* build list for functions internal to proc, and return pointer to list */
  853. static void *flist = NULL;
  854. void *
  855. f_proc() {
  856.     int  (*func)();
  857.     if (!flist) flist = makelist(sizeof(int (*)()),10);
  858.     /* put functions on flist, and give 'em names */
  859.     func = foo; pappendlist(flist,&func,"FOO",NULL);
  860.     func = goo; pappendlist(flist,&func,"GOO",NULL);
  861.     func = poo; pappendlist(flist,&func,"POO",NULL);
  862.     return flist;
  863. }
  864.  
  865. /* our proc function */
  866. void
  867. proc() {
  868.     printf("In function proc\n");
  869. }
  870.  
  871. main() {
  872.     void *l_proc;
  873.     /* get list of proc's functions */
  874.     l_proc = f_proc();
  875.     /* invoke each of the functions with arguments */
  876.     funclist(l_proc,"FOO",1,2,3,4,0);
  877.     funclist(l_proc,"GOO","line 1", "line 2", "line 3", NULL);
  878.     funclist(l_proc,"POO","some text", 666);
  879.     /* finally, call proc */
  880.     proc();
  881. }
  882.  
  883.  
  884.  
  885.